skills(pm-dispatch): charter revision — rulings A/③/C, governed-surface tiering, ui/triage lane lines (#17942 chain) - #18018
Conversation
…iage is the sole producer of grading, routing and dedupe Charter revision, chain head card 17942 (rules layer). Three rulings land here, quoted verbatim: - Q1 and Q2 (director seat, decision batch 131 item 1, 2026-09-13): 「同意」 to `1A(+三类表)·2(1)·3A·4B` — the claiming seat owns a card to MERGED; a cross-lane surface found after dispatch imports an isolated contract-review-tier review whose record carries `Implemented-by:` / `Reviewed-by:`; `pm:retriage` re-routing is pre-dispatch only; the spec seat keeps the intake of NEW `packages/spec` work; derived work in three classes (in-scope ⇒ sub-issue owned by the claiming seat at inherited priority; unclaimed blocker ⇒ the blocked seat claims and does it, any size; in-flight blocker ⇒ wait, `pm:blocking` ranks it first; incidental ⇒ a separate card). - The seat's plan, accepted verbatim: 「以上接受你的建议。」 - Ruling ③ (skills seat record, 2026-09-13T09:51Z): 「同意」 to the five points — 「一律经过分诊。定级、路由、查重、跨仓 shadow 检查、`duplicate_of` 关单,全部收回分诊席一个人做」; 「唯一例外:在飞卡的衍生子卡」; 「立卡者不查重,只在卡面附 3–5 个查重词」; 「查重缓存住在分诊席自己的容器里」. Q3 (self-routing / self-grading) is WITHDRAWN; no self-routing text had reached SKILL.md (git grep -E '自路由|自定级|self-rout' over origin/main exits 1, control 「分诊座位唯一」 hits), so nothing comes out. SKILL.md (812 → 811 in this commit; the family PR nets 0): - 多仓协调: 「跨座位转移 … 唯一豁免:简单阻塞项直接接手」 becomes 认领即跟到 MERGED plus the imported-review record line (+1); 「凡触 packages/spec 一律转」 narrows to NEW spec work; 「跨仓查重/shadow 检查恒归中央」 is deleted — the rule survives in the rewritten 分诊座位唯一生产 line (查重 / shadow / duplicate_of named) and in core-rules 多仓协调; the 单车道仓 repo:* 席 restatement is deleted — it survives at the 单车道仓 … 自理机械三务 line of the same section and the skills-lane finding self-triage line of 分诊座位职责. - 域车道: domain:* production gains the one ruled exception; the third boundary-crossing channel is named. - Epic 子树车道: 衍生问题三分 is deleted — generalised to every dispatched card in 执行座位职责, where the four 简单阻塞项 lines are rewritten as the three-class rule and the blocker rules (the S-level cap is lifted by the ruling; the incidental class survives at 顺带发现 ⇒ 独立立单). - 分诊座位职责: the triage-side dedupe cache line (+1) — lanes/triage.md is at 7/7 with its one spendable line taken by ruling B, so the cache rule lands in the rules layer the triage seat reads. - 平台读数纪律 and 报告契约: 立单前查重 → 立卡者附查重词; 立卡查重先行 → 立卡附查重词. core-rules.md (151/151): mirrors of every moved rule — dedupe keywords, triage as the sole producer including 查重, follow-through plus new-spec intake, the blocker rule, the domain-label exception. Not in this commit (references layer, follow-up PR): contract-review.md 复核归属与资格 / 独立性件 and dispatch-runbook.md 跨车道简单阻塞项直接接手. The 「分诊不重指派」 wording that option B named does not exist in the instruction tree (git grep exits 1), so there is nothing to narrow. Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
…s hand-merged, pm-dispatch references land after in-seat contract-tier review Ruling on card 17950 (live chat with the skills seat, 2026-09-13T07:2xZ–07:4xZ), maintainer verbatim: 「收窄受管面,但是 skills 是不是还是应该我来确认?」, then to the seat's boundary — 「**规则层(你确认)**:所有 SKILL.md 级的规则文本——发布的 `skills/**`(两个仓)、`.claude/skills/*/SKILL.md`(含 pm-dispatch 本体和内部 playbook)、`core-rules.md`、`.claude/agents/**`、hooks、settings、`AGENTS.md`、`CLAUDE.md`、ADR。**事实层(席内契约复审档复核后入队)**:只有 `.claude/skills/pm-dispatch/references/**`」 — 「我点头」. SKILL.md 〈复核〉 (net 0): the three skills-lane self-landing lines (diff 含 .md ⇒ 四件套 / 纯代码面 including `.claude/` hooks, workflows and settings ⇒ skills 席自审 / 直接落地 ⛔ 不推维护者) are replaced by three lines — the non-governed pure-code path (`scripts/pm/`) keeps its in-seat contract-tier self-review and landing; the two-layer definition; the per-layer landing. The old carve-out that let `.claude/` hooks, workflows and settings PRs land on the skills seat's own review is superseded: the ruling names hooks and settings in the rules layer. The ACCEPT fork line now reads 命中规则层. core-rules.md 执行座位职责: the mirror. lanes/skills.md (33/33): 受管面 PR 恒 draft 等人合 → 规则层受管 PR 恒 draft 等维护者的字; the 范围 pointer names the two layers. The objectui half (published skills/** governed there too) is already stated by lanes/ui.md 常设承诺 and the 跨仓同判 line of 〈复核〉 — measured, no line owed. AGENTS.md Prime Directive 14 (1075 → 1072 in this commit; the PR nets 0): the tiering sentence, paid inside the directive by folding the four ⛔-never spellings into one clause, dropping the node -e helper (the register sentence already names the file), and compressing the armed-or-queued paragraph and the detection sentence without removing a rule. The prose gate's anchor sentence and all five register spans are unchanged; the references prefix is spelled with a trailing slash, never as a ** glob, because check-governed-prose reds any **-shaped span outside the register. Not in this commit: the register and queue-guard script items of the card (a separate script PR) and contract-review.md 落地前检③ (references PR). Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
…eat lands a governed PR — later pushes included Ruling C on card 17971 (maintainer, live chat with the skills seat, 2026-09-13T08:50Z), verbatim: 「C. approve 后不管后续改动都由席位落地:」 — chosen over A (byte-pinned approval) and B (status quo) with the seat's own reservation in front of the maintainer. AGENTS.md Prime Directive 14: the first sentence gains its converse (confirmed by an authorized approval and then landed by the owning seat; before that approval the four acts stay forbidden); the approval sentence now says WHO lands it — the owning seat, later pushes included, re-queuing after an ejection or a rebase on its own pre-landing check — and that the maintainer's word is spent once per PR. Multi-agent discipline §7 (a): 「never enter this path, however green」 → 「on green alone」. Post-Task Checklist step 2: landing waits for the maintainer's word instead of 「by hand」 alone. Line counts unchanged at each spot. SKILL.md: red line 27 gains 「批准在案后席位落地」, paid on the same line by folding the three 永不 into one; 复核 ②: 授权批准 ⇒ 席位落地; the 批准后再推亦不过期 line now defines 席位落地 = 过落地前检、清标、ready、auto-merge, 踢出/变基同法 (its former 无批准 ⛔ 不翻 ready… half survives at red line 27). core-rules.md 红线: the mirror. Unchanged by design: the queue guards (their predicate already accepts the approval on any commit), objectui's AGENTS.md §9 (sibling repo, its own PR), and each seat's Routine text (updated at its next re-arm, per the card). Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
…e ui lane instead of pointing at it Card 17933 (p2 Task, routed into this lane by the maintainer's direct word). The maintainer read the pointer as 「不是说你的 ui 车道不需要契约复审了吗?为什么还有 `needs:contract-review`」 — a misreading that had already happened on the rule's own user. lanes/ui.md 席内判断, one line replaced (38/38): the pointer 「档位与复核豁免边界读源码与 references/contract-review.md,⛔ 不凭记忆或继承的注记」 becomes the statement synthesised from contract-review.md's three paragraphs — clause ② review applies to this lane as default-tier self-review plus gates with the label hung as usual; only the independence piece and the downgrade fuse are exempt. The per-lane applicability table and the ruling on the 「复核正为补偿低档派发而存在」 derivation live in contract-review.md and ride the references PR. Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
…graded card in pm:queue with a domain:* Card 17742, graded by the lane's self-triage (2026-09-12T02:20Z), verbatim: 「admitted as class (a) with one measured instance … Grade: pm:queue · Task · priority:p2 … (1) COUNT the population on both boards first … (2) then the cheapest of the card's three shapes that the count supports — a fourth disjunct if the population is small, the H-row home if it is large; (3) the round report's 裸卡 metric must say what it becomes」. Count, posted on the card before this edit (2026-09-13T11:46Z, repo-scoped REST lists, both boards, every page read): pm:queue ∧ domain:* ∧ ¬priority:* = 7 on objectstack and 31 on objectui — small, so the fourth disjunct is the shape; the pm:on-hold pool (69 / 46) is a decision already made and not a dispatch slot, so it stays outside the disjunct and is recorded as a measurement only. SKILL.md 分诊座位职责 (net 0): 析取 ④ takes the line of 「②③ 只取 updated_at …」 and carries that clause for ②③④; the 半状态治愈积压 line reads ②③④; the 轮次报告 裸卡数 metric line states 未定级数另计析取④. core-rules.md 分诊座位职责: the sweep mirror names 队列卡缺定级. Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
…waiting the maintainer's word as one decision batch Card 17951 (p2 Task; the reading-cost half of the maintainer's question, verbatim: 「③ 受管面手合本身也是一条队列。能否简化我的审核步骤,比如我召唤项目总监时可以批量决定?」). SKILL.md 升级与决策 (+1; the family PR nets 0): after the director's four duties, one line — every summon presents the governed drafts carrying an in-seat ACCEPT as one batch of at most five rows; the approval and the merge stay the maintainer's own clicks. AGENTS.md Prime Directive 14: the same duty as one clause of the tiering sentence (the directive is 34 lines before and after the family; 1072 → 1075 across its commits). Not in this commit: lanes/director.md and decision-analysis.md (references PR). Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
… concurrently belongs to the seat that wrote it Ruling B on card 17624 (director seat, decision batch 125 item 5, 2026-09-13): 「同意」 — the concurrency principle replaces line 7 of lanes/triage.md, a near-verbatim duplicate of the SKILL.md 分诊座位职责 line; the ratchet cap stays at 7. Precondition (ruling item 2) measured word by word: line 7 differs from the SKILL.md line only by 「分诊」 inserted (the subject the SKILL.md section already supplies) and 「裁定」 dropped (SKILL.md is the stricter spelling); neither difference carries a rule absent from SKILL.md, so B stands. lanes/triage.md line 7 (7/7): the restatement is replaced by 「补半状态前先确认无人在动;读取之后才出现的六态属他席,停手重读,⛔ 不替换」. The other three disciplines stay closed by measurement (no shared six-state writer under scripts/pm/), per the ruling's item 3. Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
…ough ruling — planned spec sub-issues still route to the spec seat, derived work stays with the claiming seat Follow-up on card 17942 (same ruling as the first commit: 「同意」 to `1A(+三类表)·2(1)·3A·4B`, and 「以上接受你的建议。」 — the spec seat keeps the intake of NEW packages/spec work; a cross-lane surface found after dispatch, packages/spec included, does not move the card). Two 座位贴协议 / Epic 子树车道 lines still said 「packages/spec 恒归 spec 座位」 and 「(sub-issue 或衍生)⇒ 照旧转 spec 座位队列」, which would have re-created the transfer the ruling removed for derived work. Both are rewritten in place (net 0): planned spec sub-issues still route to the spec seat with the epic side writing Blocked-by:; derived work follows the three-class rule of 执行座位职责. Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewHead: ① derived judgments — every changed rule read against its ruling, whole diff read line by line:
Density payments, each checked to survive elsewhere: 跨仓查重/shadow line (→ :220 + Seat measurements on the head tree ( ② semver: nothing publishes; ③ boundary flags: Implemented-by: Verdict: PASS — the rules layer of all eight rulings, each verbatim, each paid inside its file; one declared-not-enforced gap named and carded (the queue guard's tier). Governed rules layer: draft stays; Generated by Claude Code |
维护者速读(终稿)改了什么 —— 一个 PR 把今天裁过的八张卡的「规则层」文字落进章程: 为什么 —— 这些裁决今天上午已生效,章程文本落后一上午;每个席位读的是文本。 风险与代价 —— 纯文本,回滚 = revert。两点要你知道:(a) 分层现在只是「写了」,合并队列守卫( 未含 —— 批准即由本席按裁决 C 落地(四个 check 还在跑,绿了才落)。要不要批? Generated by Claude Code |
|
Ruling C landing step — skills seat (session Generated by Claude Code |
…es tier The maintainer tiered the governed surface on 2026-09-13 and the charter text landed with PR #18018, but the queue guard still demanded an authorized approval for every governed path — so the tier was declared and not enforced. The merge-group leg now classifies each governed pull request's governed paths and, when they ALL lie under `.claude/skills/pm-dispatch/references/`, accepts the skills seat's review of record on the CURRENT head in place of the approval: a `## Contract review` comment on the PR thread carrying a `Reviewed-by:` line and a `Served-tier:` reading that stands. Every other governed path is the rules layer and keeps today's predicate byte-for-byte — 16 predicate bodies are md5-identical to their pre-change selves. Recognition is IMPORTED, never re-implemented: the heading marker, the head-sha span test, the newest-of resolution, the `Reviewed-by:` key line and the `Served-tier:` reader all come from the two files that own them. Reaching them needed the module-eval cycle solved rather than worked around, so the import is lazy and this file's dispatch no longer carries a top-level await; the battery pins that precondition against this file's own source. The leg is MONOTONE by construction — consulted only for an entry no authorized approval satisfied — so it can lift a refusal and can never create one. Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8 Co-authored-by: Claude <noreply@anthropic.com>
… shape-1 red exception, the two-layer landing, the three-class blocker rule, the director batch (objectstack-ai#17942 chain, second half) (objectstack-ai#18038) Fixes objectstack-ai#17942 Fixes objectstack-ai#17950 Fixes objectstack-ai#17933 Fixes objectstack-ai#17934 Fixes objectstack-ai#17951 Dev session `session_01DAcomhvR9kKizeYgg89Vo8` on branch `claude/issue-17942-charter-references` (worktree `objectstack-issue-17942-refs`). The REFERENCES half of the charter-revision family whose rules-layer half landed as PR objectstack-ai#18018 (`9489e2c0`): four files under `.claude/skills/pm-dispatch/references/`, one commit per member card, every ruling quoted verbatim in its commit message. Governed path — the 事实层 under the landed tiering: draft, in-seat contract-tier review; ⛔ the dev never flips ready, queues or arms it. ## Rulings landed (verbatim in each commit; one line each here) - objectstack-ai#17934 (`ae17066f`) — 「1(荐):加一条例外——某个红若在该 PR 的 merge-base 提交上同名、同失败签名地红 ⇒ 不计入「全绿」;主干红仍必须立单止血(不变)。」 → contract-review.md 落地前检③ gains the exception plus the signature line (same failing step, same first error line, read from the base commit's check runs by the API, never a seat's word). - objectstack-ai#17933 (`a390e114`) — the misreading on the card, 「不是说你的 ui 车道不需要契约复审了吗?为什么还有 `needs:contract-review`」 → contract-review.md states the per-lane applicability once (spec 席达档审契约增量;余席默认档自审加门禁、挂标;豁免仅独立性件与保险丝) and closes the 「复核正为补偿低档派发而存在」 derivation (复核 ⛔ 不随派发档位免除). - objectstack-ai#17950 (`c837c7c5`) — 「我点头」 → 落地前检③ carries the two-layer landing: 规则层等维护者的字;受管路径全在 `.claude/skills/pm-dispatch/references/` 者达档过本三条入队. - objectstack-ai#17942 (`31249ef1`) — 5651976160 「同意」 · 5652079343 「以上接受你的建议。」 · 5652544529 ③ 「同意」 → 独立性件 covers a claimed card's post-dispatch cross-lane face (含 spec); 借复核不移卡,新 spec 工作恒归 spec 席; dispatch-runbook.md 〈跨车道简单阻塞项直接接手〉 rewritten as 〈在飞卡衍生与阻塞项三类细则〉 — the S-level shape and the spec-not-exempt line are gone, nothing describes the old rule. - objectstack-ai#17951 (`f0e533fc`) — 「③ 受管面手合本身也是一条队列。能否简化我的审核步骤,比如我召唤项目总监时可以批量决定?」 → director.md 职责二: enumerate, present ≤5 rows, record the answer and stop; decision-analysis.md: the row form (改了什么/为什么/席位意见/一个动作), the one exception to 六项. ## Acceptance greps (`git grep -c -F` at BASE `a0dd872c` → HEAD `f0e533fc`; every control still hits 1 → 1) | file | 0 → 1 | 1 → 0 | control | |:--|:--|:--|:--| | contract-review.md | 「同失败签名」 0→1 · 「逐车道」 0→2 · 「规则层等维护者的字」 0→1 · `.claude/skills/pm-dispatch/references/` 0→1 · 「跨车道面」 0→1 · 「借复核」 0→1 | `draft-only` 1→0 · 「达档只在 spec 席」 1→0 · 「复核正为补偿低档派发」 1→0 | `check-clause2-carriers` | | dispatch-runbook.md | 「在飞卡衍生」 0→1 · 「无主阻塞项」 0→2 | 「简单阻塞项」 1→0 · 「等一周与做十分钟」 1→0 | 「停摆复位梯度」 | | lanes/director.md | 「受管草稿批」 0→1 · 「一批」 0→1 | `draft-only` 1→0 | `pm:awaiting-maintainer` | | decision-analysis.md | 「受管草稿批」 0→1 | — | `os-decision-facets` | ## Line budgets (net 0 per file, paid by density inside the same file; each payment and where its rule survives is named in the commit) contract-review.md 60 → 60 · dispatch-runbook.md 241 → 241 · lanes/director.md 72 → 72 · decision-analysis.md 50 → 50 (`check:pm-skill-ratchet`: all four at headroom 0). `git diff a0dd872..f0e533f | grep '^+' | LC_ALL=C awk 'length-1>120'` prints nothing; the whole-file `awk 'length>120'` is empty on all four before and after. No `**` glob in prose; no issue number in operational text. ## Deviations from the dispatch, stated - director.md 职责一 :33 「受管面照旧 draft-only 加人工合并」 is not a objectstack-ai#17951 line, but it contradicted the tiering landed in PR objectstack-ai#18018 inside a file on this claim; rewritten to point at contract-review.md 落地前检③ under the four-condition in-place exemption (same defect class as this chain, mechanical, this file is on the claim, same gate family). Evidence: the director.md `draft-only` 1→0 row. - contract-review.md :12 「达档只在 spec 席」 and 落地前检 ① 「(spec 席达档)」 adjusted together with objectstack-ai#17933's per-lane line — with the independence piece open to any claimed card's cross-lane face, the fragment stopped being true. - 「新 spec 工作恒归 spec 席」 appears once, on the 复核归属 line, as the imported review's boundary; the ownership rule itself stays in SKILL.md 〈多仓协调〉 and is not restated. - Dedupe channel: the REST search endpoint is refused on this token (not repository-scoped), so the one targeted dedupe read for the finding below went through MCP `search_issues` (one call). ## Gates (`node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack`, no paths, at `f0e533fc`; all run in the foreground, exit codes captured before any pipe; `--ran`: 「14 derived, 14 run, 0 NOT-MEASURED, 0 UNRUN」) `check:pm-skill-ratchet` ✓ · `check:pm-skill-id-lint` ✓ · `check:skill-frame-sync` ✓ · `check:nul-bytes` ✓ · `check:refd-timer-probe` ✓ · `check:doc-authoring` ✓ · `check:pm-governed-merges` ✓ (self-test, 317 assertions) · `check:agent-test-spelling` ✓ · `check:driver-memory-census` ✓ · `check:watch-hint-literal` ✓ · `check-closing-keyword-parity` (+ self-test) ✓ · `check-comment-mask-corpus` ✓ · `@objectstack/lint check:doc-formula-expressions` ✓ (first run exit 3 PREREQUISITE NOT MET — formula/lint unbuilt; built under the verify lock, 3m35s shared-box, then ✓). Beyond the derivation: `check:pm-governed-prose` ✓ (its two regions are untouched). Pre-push `check:commit-card-trailers` ✓ over the five commits. No package touched ⇒ no build/test closure owed. Changeset: `.claude/**` publishes nothing ⇒ `skip-changeset` label. ## 未含 - The queue guard's tier (objectstack-ai#18020, in flight): until it lands, the merge-group leg still refuses a `references/`-only governed PR without an authorized approval — so this PR carries the four-piece as well and lands under ruling C on whichever comes first; nothing in the text claims the guard enforces the tier today. - `landing-operations.md` :27–:28 (every governed hit ⇒ 人工合并道) and `lanes/ui.md` :22 (凡触 spec 一律转) still carry pre-ruling wording — outside this claim's file surface; filed as bare card objectstack-ai#18037 with dedupe keywords. objectstack-ai#18019 covers ui.md :25, os-dev.md 先搜再立 and the SKILL.md rows. ## 维护者速读(草稿) **改了什么**:把本周裁决在 PM 章程「事实层」(pm-dispatch 的 references 目录)落地:落地前检③加「主干上同名同失败签名的红不计入全绿」例外,并写明受管面两层落地(规则层等你的字,references 目录经席内契约复审档复核后入队);契约复核细则逐车道写清谁复核、怎么复核、豁免只有两件(独立性件、降档保险丝),并写明认领席派发后碰到的跨车道面(含 spec)借隔离复核、卡不换席;runbook 的「简单阻塞项直接接手」改写为衍生子卡 / 无主阻塞项 / 在飞阻塞项三类细则;总监席章程与决策写法加上「带席内 ACCEPT 的受管草稿每场呈一批 ≤5 行」的动作。四个文件行数全部不变,每处新增都在同文件删重付账。 **为什么改**:规则层已在 PR objectstack-ai#18018 落地,这些是它点名「另起 references PR」的对应细则;每条裁决原文逐字引在各 commit。 **风险与代价(含回滚)**:不发布任何包、无 changeset;纯 references 文本,回滚 = revert 本 PR。付账删掉的四条(受管面人合不替代复核、总监席唯一裁决者与召唤仓、总监席不受保险丝、容器 403 走 MCP)各在 SKILL.md 或 contract-review.md 有存活处,commit 里逐条点名。 **席位意见**:(席位填) **你要做的**:队列守卫的分层(objectstack-ai#18020)落地前,这张 references PR 仍要你的一次批准;落地后此类 PR 不再找你。 **一句问**:director.md 职责一那句「受管面照旧 draft-only 加人工合并」随本 PR 改为指向两层落地,同意吗(是/否)? --- _Generated by [Claude Code](https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
… tier (objectstack-ai#18036) Fixes objectstack-ai#18020 Part of objectstack-ai#17950. The maintainer tiered the governed surface on 2026-09-13 (「我点头」) and the charter text landed with PR objectstack-ai#18018, but `check-governed-queue-guard.mjs` still demanded an authorized approval for every governed path — the tier was declared, not enforced. The merge-group leg now learns it. ## What changed A governed pull request whose governed paths **all** lie under `.claude/skills/pm-dispatch/references/` is satisfied by the skills seat's **review of record on the current head** — a `## Contract review` comment on the PR thread carrying a `Reviewed-by:` line and a `Served-tier:` reading that stands — in place of the approval. One rules-layer path in the same diff and today's predicate is the only way through. **Monotone by construction.** The tier leg is consulted *only* for an entry no authorized approval satisfied, so it can lift a refusal and can never create one. Nothing that passes the queue today newly refuses. **Recognition is imported, never re-implemented** — the heading marker, head-sha span test and newest-of resolution (`check-half-states.mjs`), the `Reviewed-by:` / `Served-tier:` readers (`check-clause2-carriers.mjs`). Zero new parsers; `check-clause2-carriers.mjs` carries one **export-only** change (`const` → `export const REVIEWED_BY_LINE`, value expression md5-identical). ## Acceptance greps (both directions) | reading | before | after | | --- | ---: | ---: | | `REFERENCES_TIER_PREFIX` in the guard | 0 | 9 | | `readServedTier` / `servedTierStands` imported | 0 / 0 | 4 / 4 | | `GOVERNED_APPROVERS` (lit control — still hits) | 34 | 39 | | self-test cases | 183 | 229 | | the tier VALUE spelled in the guard | 0 | 0 | | predicate bodies md5-identical to their pre-change selves | — | **16 of 16 untouched** | ## Two measurements the route turned on 1. **The cycle is real, and indirect.** A module-scope import of the recognisers deadlocks (node exits 13, "Detected unsettled top-level await") — measured directly *and* through `check-clause2-carriers.mjs`, which imports H31's file. So the import is **lazy**, which is legal only because this file's dispatch no longer carries a top-level `await`. That precondition is pinned against this file's own source; ablation D (restoring `await main()`) reds exactly that one case, and ablation C (in the self-test dispatch) reproduces the exit-13 deadlock. 2. **The thread read widens no scope.** `GET /repos/{o}/{r}/issues/{n}/comments` answers `X-Accepted-GitHub-Permissions: issues=read; pull_requests=read`, and GitHub documents the semicolon as separating *alternative* permission sets. The workflow's existing `pull-requests: read` is sufficient; ⛔ no workflow change. ## Reverse verification (mutate → prove on disk → run → restore) | ablation | cases red of 229 | | --- | ---: | | A — drop the prefix's trailing slash | 2 | | B — `entrySatisfied` accepts any record state | 12 | | C — top-level `await` in the self-test dispatch | exit 13, deadlock | | D — top-level `await` in the live dispatch | 1 (the precondition pin) | Each leg proved its mutation on disk before running, and its restore by blob hash against `HEAD`. ## Acceptance notes - `AGENTS.md` PD objectstack-ai#14's sentence 「the queue guard refuses an unpinned governed diff」 stays true: a references-only PR is pinned by its record. No prose changed; `check:pm-governed-prose` is not in the derived set for this diff and is green when run anyway. - Noted, not filed: `makeLabelReader`'s docblock says the issues-labels route "needs `issues: read`, which this workflow does not grant". The live API answers `issues=read; pull_requests=read` for it too, so the stated reason is stale — the choice to read the pull object is still right (it reuses a call the leg already makes). Successor: whoever next edits that reader, in this same file. Authored by the `domain:skills` seat, session `session_01DAcomhvR9kKizeYgg89Vo8`. ## Gates (all at `f088df57`) `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived **37** families; all 37 run, every one with its exit code captured before any pipe, all **0**. `--ran` reconciles: *37 derived, 37 run, 0 NOT-MEASURED (a DERIVED zero), 0 UNRUN*. Includes `check:pm-dispatch-gates` (1682 self-test cases), `check:pm-clause2-carriers`, `check:nul-bytes`, `check:refd-timer-probe`, `check:closing-target-claim`, `check:whole-set-label-write`, and the guard's own `--self-test` (229 cases). `check:pm-governed-prose` is **not** in the derived set for this diff — no prose surface changed — and was run anyway: green, *2 instruction surfaces name all 5 registered governed surfaces and claim no others*. `eslint . --no-inline-config` ran the **whole** population rather than a narrowing: **6722 files, 0 errors, 0 warnings**. No `parserOptions.project` and no typed rules are configured, so no untouched file's verdict can move with this diff. --- _Generated by [Claude Code](https://claude.ai/code)_ Co-authored-by: Claude <noreply@anthropic.com>
…he pre-ruling landing (objectstack-ai#18148) Fixes objectstack-ai#18083 `scripts/pm/check-governed-queue-guard.mjs` decides on an authorized APPROVED review and has since the 2026-09-04 predicate landed. What had not moved was the text a seat is told to consult: the docblock called a draft awaiting the maintainer's own merge the regime's terminal state, and the printed remedy's preferred option told a seat to take the PR out of the queue "and leave the merge to the maintainer". Since the charter chain landed (PR objectstack-ai#18018 `9489e2c0`, PR objectstack-ai#18038 `c185d087`, PR objectstack-ai#18051 `137eb00e`) the rule is ruling C — issue objectstack-ai#17971, maintainer 2026-09-13, verbatim and untranslated: > C. approve 后不管后续改动都由席位落地: So the narration under-permitted: it told a seat not to do the thing the rule now says it should do once an authorized approval is on record. ## What moved Wording only. ⛔ No decision branch changed — `entrySatisfied`, the approval reduction, the tier split and every exit code are untouched. Anchored by content, not by line number. 1. **Docblock, the "why the PR leg must not redden" paragraph.** The healthy resting state is now a draft *waiting for an authorized approval*, in the landed rule's own words from `.claude/skills/pm-dispatch/references/landing-operations.md`: 「四件套留 draft 等人批,⛔ 不翻正式不入队;获授权批准后认领席落地。」 2. **Docblock, a new paragraph for what happens after the approval** — ruling C, quoted verbatim, plus `SKILL.md`'s operational half: 「席位落地 = 过落地前检、清标、ready、auto-merge,踢出/变基同法。」 The seat's ready → enqueue is now stated as the correct next act there rather than a violation. 3. **Docblock, the "this guard cannot stop a direct merge" paragraph.** The direct merge is now the OTHER landing rather than the only one — `references/core-rules.md`: 「受管面由维护者人合或授权批准后席位落地」. The objectstack-ai#11387 measurement it cites is kept verbatim as history. 4. **The `pull_request` leg's EARLY WARNING rendering.** The ⛔ list (flip ready / enqueue / arm auto-merge) is now explicitly conditional — "while no authorized APPROVED review is on record", with AGENTS.md Prime Directive objectstack-ai#14's own "lift only for that approval" — and a new ✅ line says what a seat DOES do after the approval. 5. **The `merge_group` refusal remedy.** Steps 1 → 2 are now an order rather than a menu: out of the queue first, then the authorized approval, and the CLAIMING SEAT lands it from there. The unapproved direct merge (人工直合) is kept as the landing that PR still has. 6. **Two internal comments** that restated the same pre-ruling shape: the tier-default asymmetry cost (was "costs one hand merge") and the exit-code precedence note. The references tier is untouched and still says the in-seat review of record lands it: remedy option 3 renders byte-for-byte as before, and both of its pins (offered on a references-only refusal, withheld on a rules-layer one) still pass. ## Acceptance readings Taken on `a2e4cd7d9`, in the worktree, against merge base `a90a9f267`. **The two pre-ruling phrases, in the narration and the printed text: N → 0.** | reading | before | after | |---|---|---| | `git grep -c -E 'leave the merge to the maintainer\|human merge IS the review record'` | 2 | 2 | | … of those, hits in narration or printed remedy | 2 | **0** | | … of those, hits inside the self-test pin that FORBIDS them | 0 | 2 | Both remaining hits are the new negative assertion itself — a comment and the regex literal in `⛔ a-refusal-never-tells-a-seat-to-leave-the-merge-to-the-maintainer-nor-calls-that-merge-the-record`. A pin has to name what it forbids; neither is text the guard ever prints. **The landed phrase: 0 → 5** (`git grep -c 'CLAIMING SEAT lands\|claiming seat lands'`). **Every hit of the pre-ruling wording enumerated** (`git grep -n -E 'hand merge|human merge|leave the merge|人工合'`), 6 before → 4 after, and each remaining one accounted for: - `:44` 「人工合并即人工审核」 (docblock) — **moved**. - `:52` "the human merge IS the review record" (docblock) — **moved**. - `:536` "costs one hand merge" (tier-default comment) — **moved**, now "costs one authorized approval". - `:1171` 「人工合并即人工审核」 (EARLY WARNING rendering) — **moved**. - `:1242` "leave the merge to the maintainer. A human merge" (remedy) — **moved**. - `:2010` (was `:1983`) the `objectstack-ai#9319` replay fixture's name, quoting PR objectstack-ai#9238's own body: "a .claude/skills PR whose own body said 'awaiting a human merge'" — **stays**. It is a historical measurement naming what that PR said in 2026; rewriting it would falsify the fixture. - `:2429`, `:2436`, `:2468` — **new**, the three negative pins (two English phrases, one 人工合并即人工审核). **Self-test:** `node scripts/pm/check-governed-queue-guard.mjs --self-test` :: exit 0, **233 cases before → 238 after** (5 added, none removed, no battery floor lowered). **Diff surface:** `git diff --stat a90a9f2` names exactly one file, `scripts/pm/check-governed-queue-guard.mjs`, 104 insertions / 32 deletions. `origin/main` advanced under this worktree during the run (`a90a9f267` → `739ab526d`, a shared-ref hazard AGENTS.md names), so the anchor above is the merge base, not the moving ref. **Governed?** No — `node scripts/pm/check-governed-merges.mjs --test scripts/pm/check-governed-queue-guard.mjs` :: exit 0, "NOT governed — ordinary queue landing applies". This PR is opened as a draft and the seat lands it; nothing here flips ready or arms anything on its own. ## Reverse verification — the new pins can actually fail One-shot, from the committed state, with a `trap … EXIT INT TERM` restoring absolute paths. Predicted direction: **turns red**. - HEAD blob `f7938efe94a20f34a3c1e6f07e2aaca393f16a47`. - Mutation: the remedy's step-2 line rewritten back to the pre-ruling wording. On-disk observation, anchored on both texts: landed anchor 1 → **0**, injected stale phrase 0 → **1**; blob `87b912dbc8acaf5af5d02fb86cc06eb2bcffd986` ≠ HEAD blob, so it reached disk. - Mutated leg: `--self-test` :: **exit 1**, `✗ 2 of 238 case(s) failed` — exactly `a-refusal-orders-the-remedy-DRAFT-then-the-authorized-APPROVAL-then-the-CLAIMING-SEAT-lands-it` and `⛔ a-refusal-never-tells-a-seat-to-leave-the-merge-to-the-maintainer-nor-calls-that-merge-the-record`. - Restore leg: `git checkout HEAD -- FILE` → blob back to `f7938efe…` (byte-identical), `git diff HEAD` empty, `git status --porcelain` empty, anchor restored 1, injected 0. - Restored leg: `--self-test` :: exit 0, 238 cases pass. ## Gates Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths, three-dot against merge base `a90a9f267`) — **33 commands, all run in the foreground, every exit code captured before any pipe, all `exit 0`.** Reconciled: ``` node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran RAN_FILE Run reconciliation — 33 derived, 33 run, 0 NOT-MEASURED, 0 UNRUN. ✓ 33 derived famil(ies) accounted for — a DERIVED zero — all 33 recorded an exit code and none of them is 3. ``` Including `node scripts/pm/check-governed-queue-guard.mjs --self-test` :: exit 0 and `pnpm check:nul-bytes` :: exit 0. `pnpm check:pm-governed-merges` :: exit 0 was run too, though the derivation does **not** place it for this path — it is a `--self-test`-only checker-health family here, so its green grades that checker's fixtures, not this diff. Control characters: `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` over the changed file — no hits. No changeset: `scripts/pm/**` ships in no package's `files[]`, so this publishes nothing — the `skip-changeset` label carries it. ## Acceptance notes Two observations outside this card's one-file surface, noted and not filed (this seat's write budget for the round is the branch push, this PR, the label and one report comment): - `scripts/pm/check-governed-merges.mjs` :140 and `scripts/check-required-contexts.mjs` :288 both still say "a human merge IS the review record" for a governed PR. Neither is wrong — it is one of the two terminals the charter names 「终局两条:人工直合即审核记录;授权批准 ⇒ 席位落地。」 — but neither mentions the second one. That is an omission rather than a contradiction, so it is not the class this card is. Issue objectstack-ai#18083 fences the first file off from this PR by name. - `.claude/hooks/guard-governed-enqueue.sh` :548 was checked and is already ruling-C shaped (its steps read draft → wait for the approval → "Then enqueue"), so it needed nothing. _Generated by [Claude Code](https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8)_ --- _Generated by [Claude Code](https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8)_ Co-authored-by: Claude <noreply@anthropic.com>
Fixes #17971
Fixes #17742
Fixes #17624
Part of #17942
Part of #17950
Part of #17933
Part of #17934
Part of #17951
Dev session
session_01DAcomhvR9kKizeYgg89Vo8on branchclaude/issue-17942-charter-revision(worktreeobjectstack-issue-17942). Rules-layer charter revision for the eight-card family whose chain head is #17942. Deferred to the follow-up references PR (files occupied by PR #17990 / #17992, seat-landable once this PR lands the tiering):contract-review.md(the #17934 落地前检③ exception, #17933's per-lane table, #17950's 落地前检③ line, #17942's 复核归属 / 独立性件),dispatch-runbook.md(#17942's 跨车道直接接手),lanes/director.md+decision-analysis.md(#17951's director half); the #17950 register / queue-guard script items are their own script PR. #17934 has no edit here — its ruling lives in a deferred file.Rulings landed (verbatim, one commit per card)
1A(+三类表)·2(1)·3A·4B; 5652079343 「以上接受你的建议。」; 5652544529 ruling ③ 「同意」 (「一律经过分诊 … 唯一例外:在飞卡的衍生子卡 … 立卡者不查重,只在卡面附 3–5 个查重词 … 查重缓存住在分诊席自己的容器里」). Q3 withdrawn — no self-routing text had reached SKILL.md (git grep -E '自路由|自定级|self-rout' origin/main -- .claude/skills/pm-dispatchexits 1; control 「分诊座位唯一」 hits), so nothing came out. The 「分诊不重指派」 wording does not exist in the tree (git grep exits 1) — nothing to narrow..claude/skills/pm-dispatch/references/**lands through the queue after in-seat contract-tier review (maintainer ruling 2026-09-13) #17950 — 「我点头」 to the boundary 「规则层(你确认)… 事实层(席内契约复审档复核后入队):只有.claude/skills/pm-dispatch/references/**」.lanes/ui.md指向条款②的适用面却不陈述它 —— 维护者据此读成「本车道无需契约复核」 #17933 — the maintainer's misreading 「不是说你的 ui 车道不需要契约复审了吗?为什么还有needs:contract-review」;lanes/ui.md:38 now states the applicability.pm:queuewith adomain:*matches none of the three disjunctions — invisible to triage, visible to the lane's candidate query #17742 — self-triage 5642823259 (fourth disjunct if the population is small); count posted on the card first (5653074219):pm:queue∧domain:*∧ ¬priority:*= 7 objectstack / 31 objectui at 2026-09-13T11:46Z.lanes/triage.md:7 differed from the SKILL.md line only by 「分诊」 inserted and 「裁定」 dropped — no rule lost.Acceptance greps (
git grep -c -FatBASE→ this head; every file's control still hits)Landing is tiered/ 「两层分档」GOVERNED_SURFACES/ 「QA 波次由维护者手动触发」landed by the owning seatdirector seat requests as ONEA version release is performed by the maintainerLine budgets (net 0 per file, paid by density inside the file — payments named in each commit)
SKILL.md 812 → 812 (widest table row 342 B, untouched); core-rules.md 151 → 151; AGENTS.md 1075 → 1075 (widest row 768 B, untouched; the
node -ehelper line under PD #14 is the one deletion that is not a rule); lanes/ui.md 38 → 38; lanes/triage.md 7 → 7; lanes/skills.md 33 → 33. Every added line ≤ 120 B (git diff BASE..HEAD | grep '^+' | awk 'length>120'prints nothing); the whole-fileawk 'length($0)>120'baseline is 23 / 23 on SKILL.md and 15 → 14 on AGENTS.md — all table rows or the dropped helper line, the shape the ratchet exempts (the PM's "empty over edited files" expectation is false onorigin/mainalready). Decision frame block byte-identical: md53327d02c56f8a0eca88569dad2270f32(now at :733–:754).Deviations from the dispatch, stated
references/**spelling in prose:check:pm-governed-prosereds any**-shaped code span outside the register, so the tier is spelled.claude/skills/pm-dispatch/references/(AGENTS.md) and 本技能references/(SKILL.md)..claude/hooks/workflows/settings PRs self-land on the skills seat's review; the pm-dispatch: tier the governed surface — the rules layer stays hand-merged,.claude/skills/pm-dispatch/references/**lands through the queue after in-seat contract-tier review (maintainer ruling 2026-09-13) #17950 ruling names hooks and settings in the rules layer, so those three lines became the tiering lines (provenance beyond the shallow window not read).Gates (derived with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon the merged head269933d9; all 18 run in the foreground, exit codes captured before any pipe,--ranreconciled: 18 derived, 18 run, 0 unrun)check:pm-skill-ratchet✓ (SKILL.md 812/812 · core-rules 151/151 · AGENTS.md 1075/1075 · ui 38/38 · triage 7/7 · skills 33/33; both widest-row pins at headroom 0) ·check:pm-skill-id-lint✓ 27 files clean ·check:skill-frame-sync✓ ·check:pm-governed-prose✓ (5 register surfaces named, no over-claim) ·check:pm-governed-merges✓ ·check:nul-bytes✓ 8593 files ·check:refd-timer-probe✓ ·check:doc-authoring✓ ·check:required-contexts✓ ·check:watch-hint-literal✓ ·check:agent-test-spelling✓ ·check:docs-audit-scope✓ ·check:driver-memory-census✓ ·check-closing-keyword-parity(+ self-test) ✓ ·check-comment-mask-corpus✓ ·check-governed-queue-guard --self-test✓ 183 cases ·@objectstack/lint check:doc-formula-expressions✓ (first run exit 3 PREREQUISITE NOT MET — formula/lint unbuilt; built under the verify lock, 2m52s, then ✓). No package is touched ⇒ no build/test closure owed; changeset:.claude/**andAGENTS.mdpublish nothing ⇒skip-changeset.Acceptance notes (noted, not filed; 承接者 named)
.claude/agents/os-dev.md:50 「先搜再立」 still asks the dev to dedupe before filing; ruling ③ moves dedupe to triage (filer attaches keywords). 承接者: the skills seat — a class-1 sub-issue of [Decision] A claimed card follows through to MERGED; cross-lane surfaces import the review instead of exporting the card; in-scope derived work and unclaimed blockers stay with the claiming seat (maintainer question after #17718, 2026-09-13) #17942 (os-dev.md has its own ceiling; not in this PR's file surface).lanes/ui.md:25 and objectuiAGENTS.md§9 still read 「停在 draft 等人合」 — ruling C applies to objectui governed PRs too (the card names objectui#9374 / [finding] delegation-of-duty.dogfood.test.ts is a real end-to-end proof of the ADR-0091 validity window, and no authz matrix row cites it #9377). 承接者: the skills seat, sibling-repo PR.SKILL.md:113pm:retriagerow and :106 assignee row (table rows) still name 改路由 / 跨车道移交 without the pre-dispatch qualifier; the bullet 「pm:retriage改路由只对未派发卡」 governs. 承接者: whoever next edits those rows under the 342 B pin.维护者速读(草稿)
改了什么:把这周你在聊天里定下的八条裁决写进 PM 章程的规则层——认领的卡跟到合并(碰到 spec 面借复核不换席)、衍生子卡与阻塞项的三分表、定级/路由/查重收回分诊席(立卡者只附查重词)、受管面分两层(只有 pm-dispatch 的 references 目录经席内复核后入队,其余仍由你确认)、你批准之后由席位自己落地(后续推送也是)、ui 车道条款②适用面写明、分诊 sweep 补第四态、总监席把待你确认的受管草稿一批呈报、分诊席「并发出现的六态属他席」。SKILL.md、核心条款、AGENTS.md 第 14 条、三个车道文件,行数全部不变,每处新增都在同文件删重付账。
为什么改:每条都是已裁未落地的章程滞后;裁决原文逐字引在各 commit 与上文。
风险与代价(含回滚):不发布任何包、无 changeset;规则层文本改动,回滚 = revert 本 PR。风险在两处判断:AGENTS.md 第 14 条为付行数删掉了
node -e打印受管面的辅助命令(注册表所在文件仍点名);〈复核〉里「.claude/hooks/settings 纯代码面由 skills 席自审直接落地」的旧例外被你 09-13 的分层裁决覆盖,已删。未含:references 层的对应条文(contract-review.md 的落地前检③例外与逐车道适用表、dispatch-runbook.md 的接手细则、director.md 与 decision-analysis.md 的总监批呈)另起一个 references PR,待 PR #17990 / #17992 落地后由席位自落;#17950 的注册表与队列守卫脚本项另起脚本 PR。
一句问:同意「hooks/settings 的旧自审直落例外」随分层裁决一并删除吗(是/否)?
Generated by Claude Code